#pragma once

#include "MaxPoolingRBM.h"

using namespace loirey;

namespace nw_rbm
{

	class CDeepBeliefNetwork
	{
	public:
		typedef CSimpleTypeArray<int>	CMapping_of_Units;

	public:
		int Depth;
		CSimpleTypeArray<CRBM_with_MaxPooling> ListLayer;
		CSimpleTypeArray<CMapping_of_Units> ListMoU_BottomUp;
		CSimpleTypeArray<CMapping_of_Units> ListMoU_TopDown;

	public:
		CDeepBeliefNetwork();
		virtual void Clear();
		virtual void DeepClear();
		virtual void InitDepth(int Depth);
		virtual CRBM_with_MaxPooling& NewLayer();
		virtual CRBM_with_MaxPooling& GetLayer(int LayerIndex);
	public:
		virtual void SaveWeightModelToFile(string strFN_WeightModel) const;
		virtual bool LoadWeightModelFromFile(string strFN_WeightModel);
	public:
		virtual void InitUnitMapping();
		virtual void NewUnitsMapping(
			int LowerLayerIndex,
			int LowerLayerPoolingUnitIndex,
			int HigherLayerVisibleUnitIndex);
	public:
		virtual void InitWeightModel();
		virtual void InitWeightModel(RBM_FLOAT Variance);
	public:
		virtual void ClearMaxPoolingUnitsExtraEnergy(
			int BeginLayerIndex, int EndLayerIndex);
	public:
		virtual void UpdateAdjacentLayers_Energy_TopDown(
			int LowerLayerIndex);
		virtual void UpdateAdjacentLayers_Expectation_BottomUp(
			int LowerLayerIndex);
		//virtual void UpdateAdjacentLayers_Expectation_TopDown(
		//	int LowerLayerIndex);
		virtual void UpdateAdjacentLayers_State_BottomUp(
			int LowerLayerIndex);
		virtual void UpdateAdjacentLayers_State_TopDown(
			int LowerLayerIndex);
	public:
		virtual void Make_RBM_InferenceHelper(
			int LayerIndex,
			C_RBM_InferenceHelper*& p_RBM_InferenceHelper);
	public:
		virtual void ClearTrainingInfo(
			int LayerIndex);
		virtual void ComputeBothGradient(
			int LayerIndex,
			RBM_FLOAT SpaCod_SparseLevel,
			RBM_FLOAT ExampleWeight, RBM_FLOAT GradientAmendment);
		virtual void UpdateBothGradient(
			int LayerIndex,
			RBM_FLOAT LearningRate, RBM_FLOAT SpaCod_Lambda,
			RBM_FLOAT ConDiv_Decay_Mask, RBM_FLOAT ConDiv_Decay_Bias, RBM_FLOAT ConDiv_Momentum);
		virtual RBM_FLOAT GetCumulativeCosts(
			int LayerIndex,
			RBM_FLOAT SpaCod_Lambda,
			RBM_FLOAT& VisibleError, RBM_FLOAT& HiddenPenalty);
	public:
		virtual void PrepareTrainingLayer(int LayerIndex);
		virtual void FinishTrainingLayer(int LayerIndex);
	public:
		virtual void InferenceLevelUnit(
			int LevelIndex,
			bool fBottomUp, bool fTopDown,
			bool fUseMeanField);
		virtual void InferenceSubNetwork(
			int BeginLevelIndex, int EndLevelIndex,
			bool fFixInitialState,
			bool fUseMeanField,
			int AmountInteration);
	public:
		virtual void InferenceOnce_SingleLayer_BottomUp(
			int LayerIndex,
			bool fAcceptEnergyFromHigherLayer,
			bool fPassExpectationUp);
		virtual void InferenceOnce_SingleLayer_TopDown(
			int LayerIndex,
			bool fPassExpectationDown);
		virtual void InferenceOnce_SubNetwork_BottomUp(
			int BeginLayerIndex, int EndLayerIndex,
			bool fAcceptEnergyFromHigherLayer,
			bool fPassExpectationUp);
		virtual void InferenceOnce_SubNetwork_TopDown(
			int BeginLayerIndex, int EndLayerIndex,
			bool fPassExpectationUp);
		virtual void InferenceTimes_SubNetwork_BottomUp(
			int BeginLayerIndex, int EndLayerIndex,
			int AmountIteration,
			bool fPassExpectationUp);
		virtual void InferenceTimes_SubNetwork_TopDown(
			int BeginLayerIndex, int EndLayerIndex,
			int AmountIteration,
			bool fPassExpectationUp);
		virtual void FullInference_BottomUp(
			int AmountIteration,
			bool fPassExpectationUp);
		virtual void FullInference_TopDown(
			int AmountIteration,
			bool fPassExpectationUp);
	};

}

